<?php


namespace Plugin\PaypalSiteB\Controllers;

use Beike\Models\Address;
use Beike\Models\Cart;
use Beike\Models\Order;
use Beike\Models\Product;
use Beike\Models\ProductSku;
use Beike\Repositories\CartRepo;
use Beike\Repositories\CurrencyRepo;
use Beike\Repositories\OrderProductRepo;
use Beike\Repositories\OrderRepo;
use Beike\Repositories\OrderTotalRepo;
use Beike\Services\ShipmentService;
use Beike\Services\StateMachineService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Plugin\PaypalSiteB\Models\PaypalSiteAOrder;
use Plugin\PaypalSiteB\Services\AesTools;

class ApiController
{
    public function create_order(Request $request)
    {

        $allSettings = plugin_setting('paypal_site_b' . '.setting', []);
        if (empty($allSettings)) {
            return response()->json([
                'code' => -1,
                'msg'  => '未配置收款数据',
            ]);
        }
        $token = $allSettings["token"];

        $data     = file_get_contents("php://input");
        $data     = json_decode($data, true);
        $time     = $data['time'];
        $key      = md5($time . $token . $time);
        $aesTools = new AesTools($key);
        $data     = $aesTools->decrypt($data['data']);
        $data     = str_replace("paypal_site_a", "paypal_site_b", $data);
        //print_r($data);exit;
        $data    = json_decode($data, true);
        $orderNo = $data['order']['number'];
        $order   = Order::query()->where('number', $orderNo)->first();
        if ($order) {

            return response()->json([
                'code'   => 0,
                'msg'    => '',
                'status' => $order->status
            ]);

        }
        $data['order']['customer_id']         = 0;
        $data['order']['customer_group_id']   = 0;
        $data['order']['shipping_address_id'] = 0;
        $data['order']['payment_address_id']  = 0;
        //$data['order']['customer_name']       = '';
        $order                                            = $data['order'];

        if (empty($data['data']['current']['guest_payment_address'])) {
            $data['data']['current']['guest_payment_address'] = $data['data']['current']['guest_shipping_address'] = [
                "city"       => $order["payment_city"],
                "name"       => $order["payment_customer_name"],
                "zone"       => $order["payment_zone"],
                "email"      => $order["email"],
                "phone"      => $order["payment_telephone"],
                "country"    => $order["payment_country"],
                "default"    => "",
                "zipcode"    => $order["shipping_zipcode"],
                "zone_id"    => $order["payment_zone_id"],
                "address_1"  => $order["payment_address_1"],
                "address_2"  => $order["payment_address_2"],
                "country_id" => $order["payment_country_id"],
            ];
        }
        $data['data']['customer_id'] = '';
        $data['data']['customer']    = '';
        $amount                      = $data['data']['carts']['amount'];//商品总价

        $productIds = Product::query()->whereNull('deleted_at')->get(['id'])->pluck('id')->toArray();
        //查一条
        $bProductSkus = ProductSku::query()->with(['product'])->whereIn('product_id', $productIds)->where('price', '>', 0)->where('price', '<=', $amount)->where('quantity', '>', 0)->orderByDesc('price')->get();


        $bProductSkus = $this->findExactSumCombinationsDP($bProductSkus, $amount);
        $bProductSkus = array_values($bProductSkus);

        // 检测是否要补差价
        $total = 0;
        foreach ($bProductSkus as $bProductSku) {
            $subtotal = bcmul($bProductSku->price, $bProductSku->quantity, 2);
            $total    = bcadd($total, $subtotal, 2);
        }
        if ($total < $amount) {//还是有差价问题
            $remaining_product_id = isset($allSettings["remaining_product_id"]) ? $allSettings["remaining_product_id"] : null;
            if (empty($remaining_product_id)) {
                return response()->json([
                    'code' => -1,
                    'msg'  => "需要设置补差价商品",
                ]);
            }
            $remainingProductSku = ProductSku::query()->where('product_id', $remaining_product_id)->orderByDesc('id')->first();

            $position = $remainingProductSku->position + 1;
            $skuItem  = [
                "product_id"   => $remainingProductSku->product_id,
                "variants"     => json_encode($remainingProductSku->variants, true),
                "position"     => $position,
                "images"       => null,
                "model"        => $remainingProductSku->model,
                "sku"          => $remainingProductSku->sku . '-' . $position,
                "price"        => bcsub($amount, $total, 2),
                "origin_price" => bcsub($amount, $total, 2),
                "cost_price"   => 0,
                "quantity"     => 9999999,
                "is_default"   => 0,
                "created_at"   => now(),
                "updated_at"   => now()
            ];

            $pSkuId                          = ProductSku::query()->insertGetId($skuItem);
            $remaining_product_sku           = ProductSku::query()->with(['product'])->where('id', $pSkuId)->orderByDesc('id')->first();
            $remaining_product_sku->quantity = 1;
            $bProductSkus[]                  = $remaining_product_sku;
        }


        $newCarts    = [];
        $cartIndex   = 0;
        $currentCart = Cart::query()->orderByDesc('id')->first();
        if ($currentCart) {
            $cartIndex = $currentCart->id;
        }
        $carts        = $data['data']['carts']['carts'];
        $tax_class_id = $carts[0]['tax_class_id'];

        //Log::debug(json_encode($bProductSkus));

        foreach ($bProductSkus as $bProductSku) {
            $subtotal   = bcmul($bProductSku->price, $bProductSku->quantity, 2);
            $newCarts[] = [
                "cart_id"         => $cartIndex + 1,
                "product_id"      => $bProductSku->product->id,
                "sku_id"          => $bProductSku->id,
                "sku"             => $bProductSku->sku,
                "product_sku"     => $bProductSku->sku,
                "name"            => $bProductSku->product->description->name,
                "name_format"     => $bProductSku->product->description->name,
                "image"           => $bProductSku->product->image,
                "image_url"       => image_resize($bProductSku->product->image),
                "quantity"        => $bProductSku->quantity,
                "selected"        => 1,
                "price"           => $bProductSku->price,
                "shipping"        => 1,
                "price_format"    => currency_format($bProductSku->price),
                "tax_class_id"    => $tax_class_id,
                "subtotal"        => $subtotal,
                "subtotal_format" => currency_format($subtotal),
                "variant_labels"  => $bProductSku->getVariantLabel()
            ];
            $cartIndex++;
        }

        $data['data']['carts']['carts'] = $newCarts;


        try {
            DB::beginTransaction();

            $order1 = $this->create($data['data'],$order);
            StateMachineService::getInstance($order1)->changeStatus(StateMachineService::UNPAID, '', true);
            //Order::query()->where('id', $order->id)->update(['number' => $order1->number]);
            //$order1->number = $data['order']['number'];
            CartRepo::clearSelectedCartProducts(null);
            PaypalSiteAOrder::query()->insert(['order_no' => $order1->number]);

            hook_action('service.checkout.confirm.after', [
                'order' => $order1,
                'cart'  => $data['data']['carts']['carts']
            ]);

            DB::commit();
            return response()->json([
                'code'   => 0,
                'msg'    => '',
                'status' => $order1->status
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug($e);
            return response()->json([
                'code' => -1,
                'msg'  => $e->getMessage(),
            ]);
        }

    }

    public static function create(array $data,$orderParams)
    {
        $carts           = $data['carts'] ?? [];
        $totals          = $data['totals'] ?? [];
        $order = new Order($orderParams);
        $order->saveOrFail();

        OrderProductRepo::createOrderProducts($order, $carts['carts']);
        OrderTotalRepo::createTotals($order, $totals);

        hook_filter('repository.order.create.after', ['order' => $order, 'data' => $data]);

        return $order;
    }

    private function findExactSumCombinationsDP($items, $target, $results = [])
    {
        foreach ($items as $item) {
            $key       = "item_id_" . $item->id;
            $remaining = bcsub($target, $item->price, 2);//是否还有差的金额
            if ($remaining == 0) {
                if (isset($results[$key])) {
                    $results[$key]->quantity = $results[$key]->quantity + 1;
                    //Log::debug($key . '----' . $target . '---' . $results[$key]->quantity);
                } else {
                    $item->quantity = 1;
                    $results[$key]  = $item;
                }
                break;
            } else if ($remaining > 0) {//还差钱
                if (isset($results[$key])) {
                    $results[$key]->quantity = $results[$key]->quantity + 1;
                    //Log::debug($key . '----' . $target . '---' . $results[$key]->quantity);
                } else {
                    $item->quantity = 1;
                    $results[$key]  = $item;
                }
                $results = $this->findExactSumCombinationsDP($items, $remaining, $results);
                break;
            }
        }
        return $results;
    }

    /**
     * 创建 paypal 订单
     * @param Request $request
     * @return JsonResponse
     * @throws \Throwable
     */
    public function query_order(Request $request)
    {
        $allSettings = plugin_setting('paypal_site_b' . '.setting', []);
        if (empty($allSettings)) {
            return response()->json([
                'code' => -1,
                'msg'  => '未配置收款数据',
            ]);
        }
        $token    = $allSettings["token"];
        $data     = file_get_contents("php://input");
        $data     = json_decode($data, true);
        $time     = $data['time'];
        $key      = md5($time . $token . $time);
        $aesTools = new AesTools($key);
        $data     = $aesTools->decrypt($data['data']);
        $data     = json_decode($data, true);
        $order_no = $data['order_no'];

        $order = Order::query()->where('number', $order_no)->first();
        if (!$order) {
            return response()->json([
                'code' => -2,
                'msg'  => '订单创建失败',
            ]);
        }
        return response()->json([
            'code'   => 0,
            'status' => $order->status,
        ]);
    }

    public function showPayment(Request $request)
    {
        $order_no           = $request->order_no;
        $pollingPaypalTools = new \Plugin\PaypalSiteB\Services\PollingPaypalTools();
        $settings           = $pollingPaypalTools->getPollingSetting($order_no);
        if (empty($settings)) {
            die("请先配置支付帐户");
        }


        $data['order'] = Order::query()->where('number', $order_no)->first();

        $data['payment_setting'] = $settings;

        return view('PaypalSiteB::shop.payment', $data);
    }


    /**
     * 增加物流，同步物流数据
     * @param Request $request
     */
    public function shipping(Request $request)
    {
        $allSettings = plugin_setting('paypal_site_b' . '.setting', []);
        if (empty($allSettings)) {
            return response()->json([
                'code' => -1,
                'msg'  => '未配置收款数据',
            ]);
        }

        $token    = $allSettings["token"];
        $data     = file_get_contents("php://input");
        $data     = json_decode($data, true);
        $time     = $data['time'];
        $key      = md5($time . $token . $time);
        $aesTools = new AesTools($key);
        $data     = $aesTools->decrypt($data['data']);
        $data     = json_decode($data, true);


        $order_no       = $data['order_no'];
        $status         = $data['status'];
        $comment        = $data['comment'];
        $notify         = $data['notify'];
        $express_code   = $data['express_code'];
        $express_number = $data['express_number'];
        $shipment       = ShipmentService::handleShipment($express_code, $express_number);
        $order          = Order::query()->where('number', $order_no)->first();
        $data['order']  = $order;
        $request->merge($data);

        $orderStatusData = $request->all();
        //Log::debug($orderStatusData);

        $stateMachine = new StateMachineService($order);
        $stateMachine->setShipment($shipment)->changeStatus($status, $comment, $notify);
        hook_action('admin.order.update_status.after', $orderStatusData);

        return 'success';
    }

    /**
     * 获取sku数据
     * @param Request $request
     */
    public function getSkuData(Request $request)
    {
        $allSettings = plugin_setting('paypal_site_b' . '.setting', []);
        if (empty($allSettings)) {
            return response()->json([
                'code' => -1,
                'msg'  => '未配置收款数据',
            ]);
        }

        $token    = $allSettings["token"];
        $data     = file_get_contents("php://input");
        $data     = json_decode($data, true);
        $time     = $data['time'];
        $key      = md5($time . $token . $time);
        $aesTools = new AesTools($key);
        $data     = $aesTools->decrypt($data['data']);
        $data     = json_decode($data, true);


        $tmpSkusRs = ['skus' => [], 'prices' => []];
        $skus      = $data['skus'];
        if (!empty($skus)) {
            $productSkus = ProductSku::query()->whereIn('sku', $skus)->get();
            foreach ($productSkus as $productSku) {
                $tmpSkusRs['skus'][$productSku->sku] = $productSku->price;
            }
        }
        $prices = $data['prices'];
        if (!empty($prices)) {
            $productSkus = ProductSku::query()->whereIn('price', $prices)->get();
            foreach ($productSkus as $productSku) {
                $tmpSkusRs['prices'][$productSku->price] = $productSku->sku;
            }
        }
        return response()->json([
            'code' => 0,
            'msg'  => '',
            'data' => $tmpSkusRs
        ]);
    }
}
